package com.boss.salary.service.impl;

import com.boss.common.entity.WfActionDTO;
import com.boss.common.enums.ActionTypeEnum;
import com.boss.common.service.ICommonService;
import com.boss.framework.exception.AppRuntimeException;
import com.boss.salary.constant.SystemDictConstant;
import com.boss.salary.dao.*;
import com.boss.salary.entity.AgencyInfo;
import com.boss.salary.entity.AgencyVerify;
import com.boss.salary.entity.PersonExt;
import com.boss.salary.entity.SalaryWarnMonth;
import com.boss.salary.service.IAutoSubmitService;
import com.boss.salary.vo.SalaryMonthEndVO;
import com.boss.salary.workflow.service.ISalaryWorkFlowService;
import com.boss.sys.ca.user.dto.UserDTO;
import com.boss.sys.utils.SysUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class AutoSubmitServiceImpl implements IAutoSubmitService {

    @Autowired
    private IAutoSubmitDao autoSubmitDao;
    @Autowired
    private  ICommonService commonService;
    @Autowired
    private ISalaryWorkFlowService iSalaryWorkFlowService;
    @Autowired
    private IPersonExtBeginDao personExtBeginDao;
    @Autowired
    private ISalaryMonthBeginDao salaryMonthBeginDao;
    @Autowired
    private IPersonExtSubmitDao personExtSubmitDao;
    @Autowired
    private ISalaryMonthEndSubmitDao salaryMonthEndSubmitDao;
    @Autowired
    private GenerateSalaryDataServiceImpl generateSalaryDataService;
    @Autowired
    private ISalaryWarnMonthDao iSalaryWarnMonthDao;
    @Autowired
    private IAgencyVerifyDao iAgencyVerifyDao;
    @Autowired
    private IAgencyInfoDao agencyInfoDao;



    private static Logger logger = LoggerFactory.getLogger(AutoSubmitServiceImpl.class);
    /**
     * 自动上报
     * @param userDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)//@GlobalTransactional(timeoutMills=300000)
    public String autoReportSalary(UserDTO userDTO,List<String> withOutAgencyids,List<String> agencyIds,String tokenid) throws Exception {
        StringBuffer result=new StringBuffer();
        String year=iAgencyVerifyDao.currentYear(agencyIds);
        Map<String, String>  resultMap=new HashMap<>();
        Map<String, Object> nodeMap = autoSubmitDao.getWorkflowNodeConfig(userDTO.getProvince());
        if (!StringUtils.isEmpty(nodeMap) && nodeMap.size() > 0) {
            //预警月份数
            SalaryWarnMonth swm=iSalaryWarnMonthDao.getSalaryWarnMonth(userDTO.getProvince());
        // 获取所有未上报的未月结单位信息
//        List<String> agencyIds=new ArrayList<>();
//        List<AgencyVerify> list = autoSubmitDao.getNoReportAgencyData(userDTO.getProvince(),withOutAgencyids);
//            for(AgencyVerify a:list){
//                agencyIds.add(a.getAgencyId());
//            }
        agencyIds.removeAll(withOutAgencyids);
            //查询当前区划下所有禁止上报单位
            List<AgencyInfo> unableSubmitAgencys= agencyInfoDao.getSubmitAbleByAgencyIds(userDTO.getProvince(),agencyIds);
            if(!SysUtils.isNullOrEmpty(unableSubmitAgencys)){
                for(AgencyInfo agencyInfo:unableSubmitAgencys){
                    result.append(agencyInfo.getAgencyName()).append("已设置成禁止上报单位！</br>");
                    agencyIds.remove(agencyInfo.getId());//在后续操作集合中将禁止上报的单位id移除
                }
            }

        List<AgencyVerify> list=new ArrayList<>();
        List<Map<String,Object>> payList=new ArrayList<>();

        if(!CollectionUtils.isEmpty(agencyIds)) {


            List<String> notPaymentAgencyIds = new ArrayList<>();
            List<AgencyInfo> agencyInfos = agencyInfoDao.queryAgencyInfo(agencyIds);
            Map<String, String> isPaymentAgency = new HashMap<>();
            Map<String, String> agencyInfoMap = new HashMap<>();
            for (AgencyInfo agencyInfo : agencyInfos) {//将是否是需要生成支付单位的判断加到map中，后续方法取值判断用
                isPaymentAgency.put(agencyInfo.getId(), agencyInfo.getIsPaymentAgency());
                agencyInfoMap.put(agencyInfo.getId(),agencyInfo.getAgencyName());
                if ("0".equals(agencyInfo.getIsPaymentAgency())) {
                    agencyIds.remove(agencyInfo.getId());//移除实拨单位，实拨单位不冻结指标
                    notPaymentAgencyIds.add(agencyInfo.getId());
                }
            }
            //获取所有月初表不为空得单位
            List<String> notEmptybeginAgenyIds=salaryMonthBeginDao.getIsNotEmptybeginAgenyIds(userDTO.getProvince(),agencyIds);
            if(SysUtils.isNullOrEmpty(notEmptybeginAgenyIds)||agencyIds.size()!=notEmptybeginAgenyIds.size()){
                List<String> emptybeginAgenyIds=new ArrayList<>();
                emptybeginAgenyIds.addAll(agencyIds);
                emptybeginAgenyIds.removeAll(notEmptybeginAgenyIds);
                agencyIds=notEmptybeginAgenyIds;
                for (String agencyId:emptybeginAgenyIds) {
                    result.append(agencyInfoMap.get(agencyId)).append("无月初数据！,无法自动上报</br>");
                }
            }
            if(CollectionUtils.isEmpty(agencyIds)){//若校验完已没有可上报单位则直接返回检测结果
                return result.toString();
            }
            //检查指标是否足够
            logger.info("生成支付：校验指标是否充足");
            if (!"0".equals(swm.getWarnMonth())) {//预警月份不为0则校验并冻结指标
                List<Map<String, Object>> falsePayList = new ArrayList<>();
                //校验指标是否充足
                if (!CollectionUtils.isEmpty(agencyIds)) {
                    falsePayList = generateSalaryDataService.checkIsEnough(agencyIds,new ArrayList<>(), userDTO, payList, true,tokenid);
                }
                if (!CollectionUtils.isEmpty(payList)) {
//                    try {

                        //批量冻结指标
                        logger.info("==== 冻结指标开始");
                        resultMap = commonService.batchGocpurbudgetFrozen(payList, userDTO.getProvince(), year, tokenid,userDTO);
//                    } catch (Exception e) {
//                        e.printStackTrace();
//                        throw e;
//                    }

                    logger.info("==== 冻结指标结束：" + result.toString());
                }
                if (!CollectionUtils.isEmpty(falsePayList)) {
                    for (Map reMap : falsePayList) {
                        result.append(reMap.get("agency_name").toString() + reMap.get("merit_name").toString() + reMap.get("salary_name").toString() + "指标余额不足！</br>");
                    }
                }
            }
            agencyIds.addAll(notPaymentAgencyIds);//将实拨单位id添加到生成数据中
            //自动上报获取月初人员与工资数据
            try {
            if (!CollectionUtils.isEmpty(agencyIds)) {
                List<PersonExt> personExts = personExtBeginDao.queryPersonExt(userDTO.getProvince(), agencyIds);
                List<SalaryMonthEndVO> salaryMonthEndVOS = salaryMonthBeginDao.selectSalaryMonthEndWithSalaryType(userDTO.getProvince(), agencyIds);

                //将人员信息写入上报表，拆分数据导入，避免一次性数据超限
                int temp = 1000;

                    for (int i = 0; i < personExts.size(); i += temp) {
                        // 如果剩余条数不足temp，则取从当前位置到结尾。反之，取temp条
                        if (personExts.size() - i < temp) {
                            logger.info("自动上报第 " + i + " - " + personExts.size() + "  区间的人员信息！ ");
                            personExtSubmitDao.batchSavePersonExtSubmit(personExts.subList(i, personExts.size()));
                        } else {
                            logger.info("自动上报第 " + i + " - " + (i + temp) + " 区间的人员信息！ ");
                            personExtSubmitDao.batchSavePersonExtSubmit(personExts.subList(i, i + temp));
                        }
                    }

                //将人员工资信息写入上报表，拆分数据导入，避免一次性数据超限
                for (int i = 0; i < salaryMonthEndVOS.size(); i += temp) {
                    // 如果剩余条数不足temp，则取从当前位置到结尾。反之，取temp条
                    if (salaryMonthEndVOS.size() - i < temp) {
                        logger.info("自动上报第 " + i + " - " + salaryMonthEndVOS.size() + "  区间的人员工资信息！ ");
                        salaryMonthEndSubmitDao.batchSaveSalaryMonthSubmit(salaryMonthEndVOS.subList(i, salaryMonthEndVOS.size()));
                    } else {
                        logger.info("自动上报第 " + i + " - " + (i + temp) + " 区间的人员工资信息！ ");
                        salaryMonthEndSubmitDao.batchSaveSalaryMonthSubmit(salaryMonthEndVOS.subList(i, i + temp));
                    }
                }
                list = iAgencyVerifyDao.getSalaryDataByAgencyId(agencyIds);//若校验完单位id集合不为空，则查询剩余单位审核数据
            }


            List<AgencyVerify> unsubmitList = new ArrayList<>();
            if (!StringUtils.isEmpty(list) && list.size() > 0) {
                // 获取流程配置信息

                String processDefKey = nodeMap.get("process_def_key").toString();
//                    String userId = nodeMap.get("user_id").toString();
                String firstMenuId = nodeMap.get("first_menu_id").toString();
                for (AgencyVerify agencyVerify : list) {
                    agencyVerify.setIsAuto(SystemDictConstant.IS_SUBMIT);
                    // 如果单位已送审，但是未上报财政，推工作流
                    if (SystemDictConstant.IS_FALSE != agencyVerify.getIsSubmitInAgency()) {
                        // 获取工作流节点信息
                        logger.info(" === 获取工作流节点信息 ：" + agencyVerify.toString());
                        WfActionDTO<AgencyVerify> wfActionDTO = new WfActionDTO();
                        wfActionDTO.setProcessDefKey(processDefKey);
                        wfActionDTO.setBusinessKeys(agencyVerify.getBizKey());
                        wfActionDTO.setProvince(userDTO.getProvince());
                        wfActionDTO.setYear(agencyVerify.getYear());
                        String menuid = commonService.getMenuid(wfActionDTO);
                        logger.info(" === 工作流节点菜单id ：" + menuid);
                        wfActionDTO.setMenuguid(menuid);
                        // 送审
                        wfActionDTO.setActionType(ActionTypeEnum.WF_AUDIT.getActionTypeCode());
                        wfActionDTO.setBizDatas(agencyVerify);
                        wfActionDTO.setBizKeyName("bizKey");
                        wfActionDTO.setUserId(userDTO.getGuid());
                        // 执行工作流
                        logger.info(" === 送审工作流 ：" + wfActionDTO.toString());
                        iSalaryWorkFlowService.doSalaryFlow(userDTO, wfActionDTO,tokenid);

                    }
                    // 单位未操作，直接推工作流
                    else {
                        unsubmitList.add(agencyVerify);
                    }
                    // 修改上报状态

                    agencyVerify.setIsSubmitInAgency(SystemDictConstant.IS_TRUE);
                    agencyVerify.setSalaryVerifiedInAgencyCode(SystemDictConstant.IS_SUBMIT);
                    agencyVerify.setIsSalarySubmit(SystemDictConstant.IS_TRUE);
                    //autoSubmitDao.updateAgencyInfo(agencyVerify);
                }
                //批量修改上报状态

                if (!CollectionUtils.isEmpty(unsubmitList)) {
                    WfActionDTO<List<AgencyVerify>> wfActionDTO = new WfActionDTO();
                    wfActionDTO.setMenuguid(firstMenuId);
                    // 录入并送审
                    wfActionDTO.setProcessDefKey(processDefKey);
                    wfActionDTO.setActionType(ActionTypeEnum.WF_INPUT_AUDIT.getActionTypeCode());
                    wfActionDTO.setBizDatas(unsubmitList);
                    wfActionDTO.setBizKeyName("bizKey");
                    wfActionDTO.setProvince(userDTO.getProvince());
                    wfActionDTO.setYear(userDTO.getYear() + "");
                    wfActionDTO.setUserId(userDTO.getGuid());
                    // 执行工作流
                    logger.info(" === 批量录入并送审工作流 ：" + wfActionDTO.toString());
                    iSalaryWorkFlowService.doSalaryFlowList(userDTO, wfActionDTO,tokenid);
                    logger.info(" === 批量录入并送审工作流完成 ：" + wfActionDTO.toString());
                }
                logger.info(" === 自动上报修改单位上报状态 ：");
                autoSubmitDao.bachUpdateAgencyInfo(list);
            }
            } catch (Exception e) {
                logger.info("保存自动上报人员信息", e);
                if("100000".equals( resultMap.get("rscode"))){
                    //报错时解冻当前冻结指标
                    commonService.batchGocpurbudgetThaw(payList, userDTO.getProvince(), year, tokenid,userDTO);
                }
            }
        }
            }else {
                throw new AppRuntimeException("未配置工作流基础信息，无法自动上报！");
            }
        return result.toString();
    }


}
